package com.library.uiframework.activity;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import com.ali.music.navigator.backstack.FragmentBackStackManager;

/**
 * Activity的管理
 *
 * @author hu.cao
 * @version 1.0.0
 */
public class ActivityManager {

    /**
     * 保存在栈里的所有Activity
     */
    private List<Activity> mActivities = new ArrayList<Activity>();
    /**
     * 当前显示的Activity
     */
    private Activity mCurrentActivity = null;
    /**
     * 栈顶Activity
     */
    private Activity mLastActivity = null;
    /**
     * 栈顶Activity的上一个activity，解决跳转到其他应用回来以后LastActivity和CurrentActivity是一样的问题
     */
    private Activity mSavedLastActivity = null;

    private static ActivityManager sInstance;

    private static final String TAG = "ActivityManager";

    /**
     * 获取ActivityManager实例
     *
     * @return ActivityManager实例
     */
    public static ActivityManager instance() {
        if (sInstance == null) {
            sInstance = new ActivityManager();
        }
        return sInstance;
    }

    /**
     * 当Activity执行onCreate时调用 - 保存启动的Activity
     *
     * @param activity 执行onCreate的Activity
     */
    public void onCreate(Activity activity) {
        mActivities.add(activity);
    }

    /**
     * 当Activity执行onDestroy时调用 - 移除销毁的Activity
     *
     * @param activity 执行onDestroy时的Activity
     */
    public void onDestroy(Activity activity) {
        if (mLastActivity == activity) {
            mLastActivity = null;
        }

        if (mSavedLastActivity == activity) {
            mSavedLastActivity = null;
        }

        mActivities.remove(activity);
    }

    /**
     * 关闭所有activity
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public void finishActivities() {
        Log.d(TAG, "will exit app, finishActivities");
        for (Activity activity : mActivities) {
            if (Build.VERSION.SDK_INT >= 16) {
                activity.setResult(Activity.RESULT_CANCELED);
                activity.finishAffinity();
            }
            activity.finish();
        }
        mActivities.clear();
    }

    /**
     * 当Activity执行onResume时调用 - 保存当前显示的activity，更新栈顶Activity
     *
     * @param activity 执行onResume的Activity
     */
    public void onResume(Activity activity) {
//        LogUtils.i(TAG, "lookLeak onResume new activity is %s", activity.getClass().getSimpleName());
        mCurrentActivity = activity;
        //如果LastActivity和CurrentActivity相同，则说明是从其他应用返回来，此时LastActivity应该取前一次的Activity，否则和当前Activity是一个
        if (mLastActivity == activity) {
            mLastActivity = mSavedLastActivity;
        }
    }

    /**
     * 当Activity执行onPause时调用 - 清除当前显示的Activity
     *
     * @param activity 执行onPause的Activity
     */
    public void onPause(Activity activity) {
        mSavedLastActivity = mLastActivity;
        mLastActivity = activity;
    }

    /**
     * 获取当前显示的Activity
     *
     * @return 当前显示的Activity，可能为空
     */
    public Activity getCurrentActivity() {
        return mCurrentActivity;
    }

    /**
     * 获取栈顶的Activity
     *
     * @return 栈顶的Activity
     */
    public Activity getLastActivity() {
        return mLastActivity;
    }

    /**
     * 获取所有的Activities
     *
     * @return Activities
     */
    public List<Activity> getActivities() {
        return mActivities;
    }

    /**
     * 判断某个activity是否是当前activity
     *
     * @param activity activity
     * @return 是不是当前显示的activity
     */
    public boolean isCurrentActivity(Activity activity) {
        return activity != null && activity == getCurrentActivity();
    }

    /**
     * @return 最近打开的activity信息， 名称，token，topFragment
     */
    public String dumpLastActivityInfo() {
        return getActivityInfo(mCurrentActivity);
    }

    private String getActivityInfo(Activity activity) {
        if (activity == null) {
            return "null activity has no info";
        }

        StringBuilder builder = new StringBuilder("");

        builder.append(activity.getClass().getSimpleName());

        builder.append(":{");
        try {
            builder.append(", mToken").append(getField(activity, "mToken"));
            builder.append(", isFinished=").append(activity.isFinishing());
            builder.append(", action=").append(activity.getIntent());
            builder.append(", mWindow=").append(activity.getWindow().toString());
            builder.append(", mWindowManager=").append(activity.getWindowManager());
            builder.append(", mCallingActivity=").append(activity.getCallingActivity());
            builder.append(", mWindowAdded=").append(getField(activity, "mWindowAdded"));
            builder.append(", mVisibleFromClient=").append(getField(activity, "mVisibleFromClient"));
            builder.append(", mActivityInfo=").append(getField(activity, "mActivityInfo"));


            Bundle bundle = activity.getIntent().getExtras();
            if (bundle != null) {
                Set<String> keys = bundle.keySet();
                Iterator<String> it = keys.iterator();
                builder.append(", extra=");
                while (it.hasNext()) {
                    String key = it.next();
                    builder.append(key).append(",").append(bundle.get(key)).append("&");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (activity instanceof BaseActivity) {
            BaseActivity baseActivity = (BaseActivity) activity;
            FragmentBackStackManager manager = baseActivity.getFragmentBackStackManager();

            if (manager != null && manager.getTopFragment() != null) {
                builder.append(", topFragment=").append(manager.getTopFragment());
            }
        }
        builder.append("}\r\n");
        return builder.toString();
    }

    private String getField(Activity activity, String field) throws Exception {
        Field f = Activity.class.getDeclaredField(field);
        f.setAccessible(true);
        Object token = f.get(activity);

        if (token != null) {
            return token.toString();
        }
        return "null";
    }
}
